package vip.finance.makemoney.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import vip.finance.makemoney.apiSpider.snowball.SnowRealTimeResult;
import vip.finance.makemoney.common.RestEnum;
import vip.finance.makemoney.common.utils.StockUtil;
import vip.finance.makemoney.common.vo.StockRealTimeRes;
import vip.finance.makemoney.config.exception.BusinessException;
import vip.finance.makemoney.entity.Stock;
import vip.finance.makemoney.entity.UserStock;
import vip.finance.makemoney.mapper.StockMapper;
import vip.finance.makemoney.mapper.UserStockMapper;
import vip.finance.makemoney.service.IUserStockService;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * <p>
 * 自选股 服务实现类
 * </p>
 *
 * @author yangbin
 * @since 2023-02-03
 */
@Service
public class UserStockServiceImpl extends ServiceImpl<UserStockMapper, UserStock> implements IUserStockService {
    @Resource
    private StockMapper stockMapper;
    @Resource
    private RedisService redisService;

    @Caching(evict = {
            @CacheEvict(value = "cache:allUserStocks", allEntries = true),
            @CacheEvict(value = "cache:userStocks", key = "#userId")})
    @Override
    public void addUserStock(Integer userId, String stockCode) {
        if (count(Wrappers.<UserStock>lambdaQuery().eq(UserStock::getUserId, userId).eq(UserStock::getStockCode, stockCode)) > 0) {
            throw new BusinessException(RestEnum.LIMIT_WARN, "已经在自选列表了");
        }
        Stock stock = stockMapper.selectOne(Wrappers.<Stock>lambdaQuery().eq(Stock::getCode, stockCode));
        if (stock == null) {
            throw new BusinessException(RestEnum.LIMIT_WARN, "你选择的数据不存在，请重新操作");
        }
        UserStock maxSort = baseMapper.selectOne(Wrappers.<UserStock>lambdaQuery().orderByDesc(UserStock::getSortNum).last("limit 1"));
        UserStock userStock = new UserStock();
        userStock.setUserId(userId);
        userStock.setStockCode(stockCode);
        userStock.setSortNum(maxSort == null ? 1 : maxSort.getSortNum() + 1);
        save(userStock);
    }

    @Cacheable(value = "cache:allUserStocks", key = "#market")
    @Override
    public List<String> getAllUserStockCodes(String market) {
        return list(Wrappers.<UserStock>lambdaQuery().select(UserStock::getStockCode))
                .stream().map(UserStock::getStockCode).distinct().collect(Collectors.toList());
    }

    @Caching(evict = {
            @CacheEvict(value = "cache:allUserStocks", allEntries = true),
            @CacheEvict(value = "cache:userStocks", key = "#userId")})
    @Override
    public void updateUserStocks(Integer userId, List<StockRealTimeRes> argList) {
        List<UserStock> userStockList = list(Wrappers.<UserStock>lambdaQuery().eq(UserStock::getUserId, userId));
        IntStream.range(0, argList.size()).forEach(i -> argList.get(i).setSortNum(i));

        List<UserStock> updateList = new ArrayList<>();
        List<UserStock> delList = new ArrayList<>();

        for (UserStock userStock : userStockList) {
            StockRealTimeRes arg = argList.stream().filter(x -> x.getCode().equals(userStock.getStockCode())).findAny().orElse(null);
            if (arg == null) {
                delList.add(userStock);
            } else {
                //修改的值
                userStock.setSortNum(arg.getSortNum());
                updateList.add(userStock);
            }
        }
        if (!updateList.isEmpty()) {
            updateBatchById(updateList);
        }
        if (!delList.isEmpty()) {
            removeBatchByIds(delList.stream().map(UserStock::getId).collect(Collectors.toList()));
        }
    }

    @Override
    public List<StockRealTimeRes> listRealTime(Integer userId) {
        //我的股票列表
        List<Stock> stockList = baseMapper.selectUserStocks(userId);
        return stockList.stream().map(stock -> {
            StockRealTimeRes result = new StockRealTimeRes();
            BeanUtils.copyProperties(stock, result);

            SnowRealTimeResult.DataBean.ItemsBean snowRealTime = redisService.getSnowRealTime(StockUtil.getCompleteCode(stock));
            if (snowRealTime != null) {
                result.setStatusId(snowRealTime.getMarket().getStatus_id());
                result.setStatusDesc(snowRealTime.getMarket().getStatus());
                result.setCurrent(snowRealTime.getQuote().getCurrent());
                result.setPercent(snowRealTime.getQuote().getPercent());
                result.setChg(snowRealTime.getQuote().getChg());
                result.setCurrent_ext(snowRealTime.getQuote().getCurrent_ext());
                result.setChg_ext(snowRealTime.getQuote().getChg_ext());
                result.setPercent_ext(snowRealTime.getQuote().getPercent_ext());
            }
            return result;
        }).toList();
    }
}
